﻿/// <summary>
/// FileName: Scope.cs
/// Author: Jiang Xiaolong
/// Created Time: 2015.05.05
/// Version: 1.0
/// Company: Sunnytech
/// Function: 变量作用域，用于变量的管理；
///
/// Changed By:
/// Modification Time:
/// Discription:
/// </summary>
using System;
using System.Collections.Generic;

namespace Expression.impl
{
	public class Scope
	{
		private Scope _parent;

		private Dictionary<string, Variable> _context = new Dictionary<string, Variable>();

		private static Scope _root;

		private Scope()
		{

		}

		/// <summary>
		/// 创建作用域实例；
		/// </summary>
		/// <returns>当前作用域；</returns>
		public static Scope Create()
		{
			Scope result = new Scope();
			result._parent = GetRootScope();
			return result;
		}

		/// <summary>
		/// 当前作用域；
		/// </summary>
		/// <returns>当前作用域；</returns>
		private static Scope GetRootScope()
		{
			if (_root == null)
			{
				_root = new Scope();
				_root.SetVariable("PI", typeof(double)).MakeConstant(Math.PI);
				_root.SetVariable("EULER", typeof(double)).MakeConstant(Math.E);
			}
			return _root;
		}

		/// <summary>
		/// 创建作用域；
		/// </summary>
		/// <param name="parent">当前作用域；</param>
		/// <returns>当前作用域；</returns>
		public static Scope CreateWithParent(Scope parent)
		{
			Scope result = Create();
			result._parent = parent;
			return result;
		}

		/// <summary>
		/// 提取对应ID的变量；
		/// </summary>
		/// <param name="name">变量名；</param>
		/// <returns>当前对应变量；</returns>
		public Variable Find(string name)
		{
			if (_context.ContainsKey(name))
			{
				return _context[name];
			}
			if (_parent != null)
			{
				return _parent.Find(name);
			}
			return null;
		}

		/// <summary>
		/// 设置变量；
		/// </summary>
		/// <param name="name">变量名；</param>
		/// <param name="type">变量类型；</param>
		/// <returns>当前变量；</returns>
		public Variable SetVariable(string name, Type type)
		{
			Variable result = Find(name);
			if (result != null)
			{
				result.ExpType = type;
				return result;
			}
			return Create(name, type);
		}

		/// <summary>
		/// 设置变量；
		/// </summary>
		/// <param name="name">变量名；</param>
		/// <param name="type">变量类型；</param>
		/// <param name="value">变量值；</param>
		/// <returns>当前变量；</returns>
		public Variable SetVariable(string name, Type type, object value)
		{
			Variable result = Find(name);
			if (result != null)
			{
				result.ExpType = type;
				result.SetValue(value);
				return result;
			}
			return Create(name, type, value);
		}

		/// <summary>
		/// 创建变量；
		/// </summary>
		/// <param name="name">变量名；</param>
		/// <param name="type">变量类型；</param>
		/// <returns>当前变量；</returns>
		public Variable Create(string name, Type type)
		{
			if (_context.ContainsKey(name))
			{
				_context[name].ExpType = type;
				return _context[name];
			}
			Variable result = new Variable(name, type);
			_context.Add(name, result);
			return result;
		}

		/// <summary>
		/// 创建变量；
		/// </summary>
		/// <param name="name">变量名；</param>
		/// <param name="type">变量类型；</param>
		/// <param name="value">变量值；</param>
		/// <returns>当前变量；</returns>
		public Variable Create(string name, Type type, object value)
		{
			if (_context.ContainsKey(name))
			{
				_context[name].ExpType = type;
				_context[name].SetValue(value);
				return _context[name];
			}
			Variable result = new Variable(name, type, value);
			_context.Add(name, result);
			return result;
		}

		/// <summary>
		/// 获取变量名字列表；
		/// </summary>
		/// <returns>名字列表；</returns>
		public List<string> GetNameList()
		{
			List<string> nameList = new List<string>();
			foreach (string name in _context.Keys)
			{
				nameList.Add(name);
			}
			return nameList;
		}

		/// <summary>
		/// 设置变量值；
		/// </summary>
		/// <param name="name">变量名；</param>
		/// <param name="value">变量值；</param>
		public void SetValue(string name, object value)
		{
			if (_context.ContainsKey(name))
			{
				_context[name].SetValue(value);
			}
		}

		/// <summary>
		/// 该变量是否已创建！
		/// </summary>
		/// <param name="name">变量名；</param>
		/// <returns>是否已创建</returns>
		public bool IsCreated(string name)
		{
			if (_context.ContainsKey(name))
			{
				return true;
			}
			if (_parent != null)
			{
				if (_parent.Find(name) != null)
				{
					return true;
				}
			}
			return false;
		}
	}
}
